package com.binhthuan.catechist.server.bus;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;

import com.binhthuan.catechist.server.domain.AbstractObject;
import com.binhthuan.catechist.server.domain.Course;
import com.binhthuan.catechist.server.util.HibernateUtil;
import com.binhthuan.catechist.shared.constant.Parameter;

public class CourseBUS extends AbstractBUS {

    public List<Course> getAllCourses() {
        return getAll(Course.class);
    }

    public Course getCourseById(int id) {
        return get(Course.class, id);
    }

    public boolean deleteCourse(int id) {
        return delete(Course.class, id);
    }

    public Course getCourseByName(String name) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        Course result = null;
        try {
            transaction = session.beginTransaction();
            Criteria criteria = session.createCriteria(Course.class).add(Restrictions.eq(Parameter.NAME, name));
            result = (Course) criteria.uniqueResult();
            if (result != null) {
                initializeObject(result);
            }

            transaction.commit();
        } catch (HibernateException he) {
            he.printStackTrace();
            transaction.rollback();
        } finally {
            session.close();
        }

        return result;
    }

    public Course getCourseByCode(String code) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        Course result = null;
        try {
            transaction = session.beginTransaction();
            Criteria criteria = session.createCriteria(Course.class).add(Restrictions.eq(Parameter.CODE, code));
            result = (Course) criteria.uniqueResult();
            if (result != null) {
                initializeObject(result);
            }

            transaction.commit();
        } catch (HibernateException he) {
            he.printStackTrace();
            transaction.rollback();
        } finally {
            session.close();
        }

        return result;
    }

    public List<Course> getCoursesBySchoolYear(Integer yearId) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        List<Course> result = null;
        try {
            transaction = session.beginTransaction();
            Criteria criteria = session.createCriteria(Course.class).createCriteria(Parameter.YEAR).add(
                    Restrictions.eq(Parameter.ID, yearId)).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            result = new ArrayList<Course>(criteria.list());
            for (Course c : result) {
                initializeObject(c);
            }

            transaction.commit();
        } catch (HibernateException he) {
            he.printStackTrace();
            transaction.rollback();
        } finally {
            session.close();
        }

        return result;
    }

    public List<Course> getCoursesByTrainer(Integer trainerId) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        List<Course> result = null;
        try {
            transaction = session.beginTransaction();
            Criteria criteria = session.createCriteria(Course.class).createCriteria(Parameter.TRAINERS).add(
                    Restrictions.eq(Parameter.ID, trainerId));
            result = new ArrayList<Course>(criteria.list());
            for (Course c : result) {
                initializeObject(c);
            }

            transaction.commit();
        } catch (HibernateException he) {
            he.printStackTrace();
            transaction.rollback();
        } finally {
            session.close();
        }

        return result;
    }

    public List<Course> getCoursesByTrainee(Integer traineeId) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        List<Course> result = null;
        try {
            transaction = session.beginTransaction();
            Criteria criteria = session.createCriteria(Course.class).createCriteria(Parameter.TRAINEES).add(
                    Restrictions.eq(Parameter.ID, traineeId));
            result = new ArrayList<Course>(criteria.list());
            for (Course c : result) {
                initializeObject(c);
            }

            transaction.commit();
        } catch (HibernateException he) {
            he.printStackTrace();
            transaction.rollback();
        } finally {
            session.close();
        }

        return result;
    }

    public void initializeObject(Course obj) {
        Hibernate.initialize(obj.getYear());
        Hibernate.initialize(obj.getShift());
        Hibernate.initialize(obj.getVenue());
        Hibernate.initialize(obj.getGrade());
        Hibernate.initialize(obj.getTrainers());
    }

    /*
     * (non-Javadoc)
     * 
     * @seecom.binhthuan.catechist.server.bus.AbstractBUS#
     * initializeObjectForSingleSelect
     * (com.binhthuan.catechist.server.domain.AbstractObject)
     */
    @Override
    protected <T extends AbstractObject> void initializeObjectForSingleSelect(T object) {
        if (object == null) {
            return;
        }
        Course obj = (Course) object;
        Hibernate.initialize(obj.getYear());
        Hibernate.initialize(obj.getShift());
        Hibernate.initialize(obj.getVenue());
        Hibernate.initialize(obj.getGrade());
    }
}
